#include <string>
#include <iostream>
#include <string>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <pthread.h>

#include "log.hpp"

const int SIZE = 1024;
Log lg_;

void UsePage(char *argv[])
{
    std::cout << "failed Use" << std::endl;
    std::cout << argv[0] << "  [ip]  [port]" << std::endl;
}

enum
{
    SOCKET_ERR = 1
};

class SockData
{
public:
    SockData(struct sockaddr_in *server, int sockfd)
        : server_(server), sockfd_(sockfd)
    {}

public:
    struct sockaddr_in *server_;
    int sockfd_;
};


void *Recv_Message(void *args)
{
    SockData *sd_ = (SockData *)args;
    int sockfd = sd_->sockfd_;
    char buffer[2048];

    while (true)
    {

        struct sockaddr_in temp;
        unsigned int sz = sizeof(temp);
        int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (sockaddr *)&temp, &sz);

        if (n > 0)
        {
            buffer[n] = 0;
            std::cout << buffer << std::endl;
        }
    }
    return nullptr;
}

void *Send_Message(void *args)
{
    SockData *sd_ = (SockData *)args;
    int sockfd = sd_->sockfd_;
    struct sockaddr_in* server = sd_->server_;
    signed int len = sizeof(*server);

    std::string message;

    std::string prev = "client@"; 
    while(true)
    {

        write(2, prev.c_str() , prev.size());
        getline(std::cin, message);

        int s = sendto(sockfd, message.c_str(), message.size(), 0, (sockaddr *)server, len);
        if (s < 0)
        {
            lg_(Warning, "sendto fail , errno message : %s , errno : %d ", strerror(errno), errno);
            continue;
        }
    }
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        UsePage(argv);
        exit(errno);
    }

    std::string ip = argv[1];
    uint16_t port = std::stoi(argv[2]);
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        lg_(Fatal, "socket fail : errno message : %s  errno num: %d ", strerror(errno), errno);
        exit(SOCKET_ERR);
    }
    lg_(Info, "socket creat success ");

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = inet_addr(ip.c_str());
    unsigned int len = sizeof(server);


    SockData *sd = new SockData(&server, sockfd);

    // 1. 创建一个线程专门用来接受信息
    pthread_t pdt1 , pdt2;
    pthread_create(&pdt1, nullptr, Recv_Message, (void *)sd);
    pthread_create(&pdt2, nullptr, Send_Message, (void *)sd);

    pthread_join(pdt1 ,nullptr);
    pthread_join(pdt2 ,nullptr);
    return 0;
}